ESRI Integration via script
Introduction
A python script to integrate ArcGIS features with Assetic assets may be run outside of ArcGIS Desktop applications. The script needs to be executed on a machine that has ArcGIS Desktop (or ArcGIS Server) installed because it utilises the arcpy python package installed by ArcGIS. The arcpy library will also use an ESRI licence (lowest applicable licence) for the duration of the script execution.
The scripts also require the 'assetic_esri' package to be installed, as per the article ESRI Integration Introduction.
Scripted Process - New Feature Creation
This is a script that checks for features that do not have a corresponding asset in Assetic. It creates an asset in Assetic for those features and updates the feature. The script may be run periodically according to a schedule or manually initiated.
As an example the script may be run manually when all edits are complete and the spatial data edits have been committed. Typically an 'asset Id' attribute field exists for the feature class that can be used to record the generated 'asset Id'. The asset is created in Assetic, and the feature then updated to hold the 'asset Id'
Sample script - File Geodatabase
The sample script below may be copied and pasted to a text editor, and saved with a '.py' file extension. It is suggested that the script be saved as 'Assetic.CreateAssetsFromFileGDB'. This script example is for creating assets in Assetic where the source is a File Geodatabase.
- """
- Assetic.CreateAssetsFromFileGDB
- Sample script to create assets in Assetic corresponding with selected
- features from a file geodatabase
- """
- import assetic_esri
- import arcpy
- # Define the feature class in the file geodatabase. Could alternatively assign
- # a layer (.lyr)file
- lyr = arcpy.mapping.Layer(r'C:\Projects\assets.gdb\roads')
- # Define file location for log and ini file with Assetic credentials and
- # integration configuration file
- inifile = r"c:\Assetic\assetic.ini"
- logfile = r"c:\Assetic\addin.log"
- xmlfile = r"c:\Assetic\arcmap_edit_config.xml"
- ae = assetic_esri.Initialise(xmlfile, inifile, None, "Info")
- tools = assetic_esri.LayerTools()
- # define the query string for the layer we are adding
- where_clause = "assetid is null" # process fields where assetid is NULL
- # clear any current selections and apply the new query. Only features selected
- # by the query are processed
- arcpy.SelectLayerByAttribute_management(lyr, "CLEAR_SELECTION")
- arcpy.SelectLayerByAttribute_management(lyr, "NEW_SELECTION", where_clause)
- # Now create assets in Assetic for the selected features
- tools.create_asset(lyr)
Sample script - Enterprise Geodatabase
The sample script below may be copied and pasted to a text editor, and saved with a '.py' file extension. It is suggested that the script be saved as 'Assetic.CreateAssetsFromLayers.py'. This script example is for creating assets in Assetic where the source is an Enterprise Geodatabase.
- """
- Assetic.CreateAssetsFromLayers.py
- Script to create assets in Assetic from features in one or more ArcGIS layers
- This example assumes a versioned enterprise geodatabase
- Requires asset_esri v1.0.1.4 or later
- """
- import arcpy
- import assetic_esri
- import os
- def main():
- """
- Initialise the assetic_esri library. It will read the config files etc
- """
- if not initasseticesri():
- return
- # define layers to process (one or more), and the search query that
- # identifies features to process as new assets
- layers = list()
- # define the query string for the layer we are adding
- query = "assetid is null" # process fields where assetid is NULL
- # for testing, uncomment this line and specify a single record by id field
- #query = "UFI = 'rds002720978'"
- # add the layer to the list
- layers.append(("C:\Projects/TAS/SealedRoads_sde.lyr",query))
- # more layers may be added using layers.append((layername, query)) format
- # loop through layer list and process new assets
- for layer in layers:
- create_assets_for_layername(layer[0],layer[1])
- def create_assets_for_layername(layername, query=None):
- """
- For the given layername and query filter process selected features
- to create a corresponding asset in Assetic and update the feature with
- the asset friendly asset id, or the assetic internal asset guid.
- Versioned editing is assumed. A new edit session is opened for the layer
- edit
- Assumes the xml config file has the layer name (as appears in the TOC)
- :param layername: the file path and name of the layer file
- :param query: optional, but if omitted all assets are processed.
- example query strings:'assetid is null' or "externalid = ''"
- """
- # initialise assetic esri tools for layers
- tools = assetic_esri.LayerTools()
- # get workspace
- desc = arcpy.Describe(layername)
- lyr = None
- if desc.dataType == "Layer":
- # create an instance of the layer using the name
- lyr = arcpy.mapping.Layer(layername)
- else:
- # need a layer
- print("no layer defined")
- return
- # get the workspace
- arcpy.env.workspace = desc.Path
- # create edit session. If there is a workspace error try setting it to
- # the folder containing the connection. Make sure you also import os at
- # the start.
- # arcpy.env.workspace = os.path.dirname(desc.Path)
- edit = arcpy.da.Editor(arcpy.env.workspace)
- # start edit session
- edit.startEditing(False,True)
- edit.startOperation()
- ##execute asset creation
- tools.create_asset(lyr, query)
- ##finalise
- edit.stopOperation()
- edit.stopEditing(True)
- def initasseticesri():
- """
- initialise the helper module assetic_esri
- sets the paths to the xml config and ini files
- """
- appdata = os.environ.get("APPDATA")
- inifile = os.path.abspath(appdata + "\\Assetic\\assetic.ini")
- logfile = os.path.abspath(appdata + "\\Assetic\\addin.log")
- xmlfile = os.path.abspath(appdata + "\\Assetic\\arcmap_edit_config.xml")
- try:
- ae = assetic_esri.Initialise(xmlfile,inifile,logfile,"Info")
- except Exception as ex:
- print("Error initialising Addin: {0}".format(ex))
- return False
- return True
- if __name__ == "__main__":
- main()
Alternatively download the file: Assetic.CreateAssetsFromLayers.py
How it works
The script uses ESRI layer files to define the data source to integrate. A query string is used to filter the records in the layer file to select the features that are new i.e. do not have a value in the 'assetid' field.
#for the layer we are adding, define the query string query = "assetid is null" #process fields where assetid is NULL #for testing, uncomment this line and specify a single record by id field #query = "UFI = 'rds002720978'" #add the layer to the list layers.append(("C:\Projects\TAS\SealedRoads_sde.lyr",query)) #more layers may be added using layers.append((layername, query)) format
In the example above, the layer file is "C:\Projects\TAS\SealedRoads_sde.lyr", and the query filter is "assetid is null". Change these two settings in the script to suit your dataset and the script is ready to run (assuming the XML configuration file and assetic.ini configuration file are also configured).
Asset Updates via Assetic
Where Assetic is the master for asset attributes, ArcMap needs a simple way to reference the attributes. This is managed by the Assetic Python SDK tool Creating-a-Local-Backup-of-Assetic-Data-Assetic-Python-SDK-. This tool will ensure that a local copy of the attributes needed within ArcMap are available. There is no need to update the features with the attributes, a database join is sufficient.
Scripted Process - Feature Edits
As with 'New Features' a python script may be run that updates Assetic with attribute values updated in ArcMap.
Where such a script is implemented, it is treating ArcMap as the 'master' data source for those particular assets. This kind of integration is not without risk because individual fields within Assetic cannot be set as read-only, so it is possible another user has also updated those same fields via the Assetic application itself.
It may also be difficult to identify which features have changed (outside of the edit session itself), and will be dependent on site specific workflows.
Some options for identifying edited features are:
- Use of archiving is one way to detect changes
- Use an additional attribute field that can be used to flag the edit - 'last modified date' is a typical example. 'last modified date' can be enforced for Datasets via 'Editor Tracking
If the edit occurs in a different geodatabase to the 'publishing' geodatabase, and the sync with Assetic is to be actioned when the edits are published to the 'publishing' geodatabase the arcpy function arcpy.DetectFeatureChanges_management() may be used to detect changes prior to publishing.
Scripted Process - Feature Deletes
For features that are deleted, archived, or flagged as decommisioned the same integration logic as for feature edits is applied. For these features a field in Assetic would be updated to indicate the new status. It is suggested the following Assetic fields ("Management"-."Operational Details") can be used to flag this status:
- Decommissioned Date
- Asset Disposal
- Operational State
This then allows the assets to be identified within Assetic, and for the appropriate work flow to then take place in Assetic.